package com.marketing.tenant.interceptor;

import com.marketing.tenant.context.UserContext;
import com.marketing.tenant.service.TenantService;
import com.marketing.tenant.entity.Tenant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 租户上下文拦截器
 * 负责识别和设置当前请求的租户信息
 * 优先级高于权限拦截器，确保租户信息先设置
 */
@Component
@Order(1)
public class TenantContextInterceptor implements HandlerInterceptor {

    private static final Logger log = LoggerFactory.getLogger(TenantContextInterceptor.class);

    @Autowired
    private TenantService tenantService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.debug("租户上下文拦截器处理请求: {} {}", request.getMethod(), request.getRequestURI());

        try {
            // 尝试多种方式识别租户
            Long tenantId = identifyTenant(request);
            
            if (tenantId != null) {
                // 验证租户是否存在且有效
                Tenant tenant = tenantService.getTenantById(tenantId);
                if (tenant != null && tenant.getStatus() == 1) {
                    // 设置租户上下文
                    setTenantContext(tenantId);
                    log.debug("成功设置租户上下文: tenantId={}, tenantCode={}", tenantId, tenant.getTenantCode());
                } else {
                    log.warn("租户不存在或已停用: tenantId={}", tenantId);
                    // 使用默认租户
                    setTenantContext(1L);
                }
            } else {
                log.debug("未识别到租户，使用默认租户");
                // 使用默认租户
                setTenantContext(1L);
            }
            
            return true;
        } catch (Exception e) {
            log.error("租户上下文处理异常: {} {}", request.getMethod(), request.getRequestURI(), e);
            // 异常情况下使用默认租户
            setTenantContext(1L);
            return true;
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 清理租户上下文由AuthInterceptor统一处理
        log.debug("租户上下文拦截器完成: {} {}", request.getMethod(), request.getRequestURI());
    }

    /**
     * 识别租户ID
     * 按优先级尝试不同的识别方式
     */
    private Long identifyTenant(HttpServletRequest request) {
        Long tenantId = null;

        // 1. 从请求头获取租户ID (最高优先级)
        tenantId = getTenantIdFromHeader(request);
        if (tenantId != null) {
            log.debug("从请求头识别租户: {}", tenantId);
            return tenantId;
        }

        // 2. 从子域名获取租户编码
        tenantId = getTenantIdFromSubdomain(request);
        if (tenantId != null) {
            log.debug("从子域名识别租户: {}", tenantId);
            return tenantId;
        }

        // 3. 从路径参数获取租户编码
        tenantId = getTenantIdFromPath(request);
        if (tenantId != null) {
            log.debug("从路径参数识别租户: {}", tenantId);
            return tenantId;
        }

        // 4. 从查询参数获取租户信息
        tenantId = getTenantIdFromQuery(request);
        if (tenantId != null) {
            log.debug("从查询参数识别租户: {}", tenantId);
            return tenantId;
        }

        log.debug("未能识别租户信息");
        return null;
    }

    /**
     * 从请求头获取租户ID
     * Header: X-Tenant-Id: 123
     */
    private Long getTenantIdFromHeader(HttpServletRequest request) {
        String tenantIdStr = request.getHeader("X-Tenant-Id");
        if (StringUtils.hasText(tenantIdStr)) {
            try {
                return Long.parseLong(tenantIdStr);
            } catch (NumberFormatException e) {
                log.warn("请求头中的租户ID格式错误: {}", tenantIdStr);
            }
        }

        // 也支持租户编码方式
        String tenantCode = request.getHeader("X-Tenant-Code");
        if (StringUtils.hasText(tenantCode)) {
            return getTenantIdByCode(tenantCode);
        }

        return null;
    }

    /**
     * 从子域名获取租户编码
     * 例如: tenant1.example.com -> tenant1
     */
    private Long getTenantIdFromSubdomain(HttpServletRequest request) {
        String serverName = request.getServerName();
        if (StringUtils.hasText(serverName)) {
            String[] parts = serverName.split("\\.");
            if (parts.length >= 3) {  // 至少有三段: subdomain.domain.com
                String subdomain = parts[0];
                if (!"www".equalsIgnoreCase(subdomain) && !"api".equalsIgnoreCase(subdomain)) {
                    return getTenantIdByCode(subdomain);
                }
            }
        }
        return null;
    }

    /**
     * 从路径参数获取租户信息
     * 例如: /tenant/{tenantCode}/api/users
     */
    private Long getTenantIdFromPath(HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        if (StringUtils.hasText(requestURI)) {
            // 匹配 /tenant/{tenantCode}/... 模式
            if (requestURI.startsWith("/tenant/")) {
                String[] pathParts = requestURI.split("/");
                if (pathParts.length >= 3) {
                    String tenantCode = pathParts[2];
                    return getTenantIdByCode(tenantCode);
                }
            }
        }
        return null;
    }

    /**
     * 从查询参数获取租户信息
     * 例如: ?tenantId=123 或 ?tenantCode=demo
     */
    private Long getTenantIdFromQuery(HttpServletRequest request) {
        // 直接获取租户ID
        String tenantIdStr = request.getParameter("tenantId");
        if (StringUtils.hasText(tenantIdStr)) {
            try {
                return Long.parseLong(tenantIdStr);
            } catch (NumberFormatException e) {
                log.warn("查询参数中的租户ID格式错误: {}", tenantIdStr);
            }
        }

        // 获取租户编码
        String tenantCode = request.getParameter("tenantCode");
        if (StringUtils.hasText(tenantCode)) {
            return getTenantIdByCode(tenantCode);
        }

        return null;
    }

    /**
     * 根据租户编码获取租户ID
     */
    private Long getTenantIdByCode(String tenantCode) {
        try {
            Tenant tenant = tenantService.getTenantByCode(tenantCode);
            return tenant != null ? tenant.getId() : null;
        } catch (Exception e) {
            log.warn("根据租户编码查询租户失败: {}", tenantCode, e);
            return null;
        }
    }

    /**
     * 设置租户上下文
     */
    private void setTenantContext(Long tenantId) {
        UserContext.UserInfo userInfo = UserContext.getUser();
        if (userInfo != null) {
            // 更新现有用户信息的租户ID
            userInfo.setTenantId(tenantId);
        } else {
            // 创建临时用户信息，只包含租户ID
            UserContext.UserInfo tempUserInfo = new UserContext.UserInfo();
            tempUserInfo.setTenantId(tenantId);
            UserContext.setUser(tempUserInfo);
        }
        log.debug("租户上下文已设置: tenantId={}", tenantId);
    }
}